import 'dart:convert';
import 'dart:typed_data';

import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:flutter/foundation.dart';
import 'package:logger/logger.dart';
import 'package:xim/common/util/datetime.dart';
import 'package:xim/common/util/round.dart';

/// AES加密算法

class AES {

  static Logger log = Logger();

  static String? _padding = null;
  // TODO creatorAccount
  static final encrypt.IV _iv = encrypt.IV.fromUtf8("%^&*()#%^&*@!");

  /// 加密
  static Uint8List encryptAesBytes({required String aesKey, required List<int> data}){
    log.i("start aes encrypt");
    final key = encrypt.Key.fromUtf8(aesKey);
    final encrypter = encrypt.Encrypter(encrypt.AES(key, padding: _padding));
    var encryptBytes = encrypter.encryptBytes(data, iv: _iv);
    log.i("aes encrypt end");
    return encryptBytes.bytes;
  }

  /// 加密, 异步化
  static Future<Uint8List> encryptAesBytesAsync({required String aesKey, required List<int> data}){
  log.i("开始加密:${data.length/1024}, ${DateTime.now().format("yyyy-MM-dd HH:mm:ss")}");
    final key = encrypt.Key.fromUtf8(aesKey);
    return Future((){
      final encrypter = encrypt.Encrypter(encrypt.AES(key, padding: _padding));
      var encryptBytes = encrypter.encryptBytes(data, iv: _iv);
      log.i("分片(size=[${data.length/1024}])加密完成 ${DateTime.now().format("yyyy-MM-dd HH:mm:ss")}");
      return encryptBytes.bytes;
    });
  }

  /// 加密, 多线程化
  static Future<Uint8List> encryptAesBytesIsolate({required String aesKey, required List<int> data}){
    log.i("开始加密:${data.length/1024}, ${DateTime.now().format("yyyy-MM-dd HH:mm:ss")}");
    final key = encrypt.Key.fromUtf8(aesKey);
    var res = compute((message){
      final encrypter = encrypt.Encrypter(encrypt.AES(key, padding: _padding));
      var encryptBytes = encrypter.encryptBytes(data, iv: _iv);
      log.i("分片(size=[${data.length/1024}])加密完成 ${DateTime.now().format("yyyy-MM-dd HH:mm:ss")}");
      return encryptBytes.bytes;
    }, (key, data));
    return res;
  }

  /// 解密
  static Uint8List decryptAesBytes({required String aesKey, required List<int> encryptData}){
    var encrypted = encrypt.Encrypted(Uint8List.fromList(encryptData));
    final key = encrypt.Key.fromUtf8(aesKey);
    final encrypter = encrypt.Encrypter(encrypt.AES(key, padding: _padding));
    final decrypted = encrypter.decryptBytes(encrypted, iv: _iv);
    return Uint8List.fromList(decrypted);
  }

  static String encryptAes({
    required String plainText,
    required String aesKey
  }) {
    final key = encrypt.Key.fromUtf8(aesKey);
    final encrypter = encrypt.Encrypter(encrypt.AES(key, padding: _padding));
    final encrypted = encrypter.encrypt(plainText, iv: _iv);
    return encrypted.base64;
  }

  static String decryptAes({
    required String encryptedBase64Text,
    required String aseKey
  }) {
    var encryptedText = base64.decode(encryptedBase64Text);
    var encrypted = encrypt.Encrypted(encryptedText);

    final key = encrypt.Key.fromUtf8(aseKey);
    final encrypter = encrypt.Encrypter(encrypt.AES(key, padding: _padding));
    final decrypted = encrypter.decrypt(encrypted, iv: _iv);
    return decrypted;
  }

  /// 随机生成一个AES key
  static String roundAesKey({AesKeySize size=AesKeySize.small}){
    int len = size.len~/8;
    return  RoundUtility.roundString(len);
  }

}

enum AesKeySize {
  small(len: 128),
  middle(len: 192),
  long(len: 256),
  ;
  final int len;
  const AesKeySize({required this.len});
}
